package com.molichuxing.services.business.service.impl;

import com.molichuxing.framework.exception.BizException;
import com.molichuxing.services.business.convertor.Convert;
import com.molichuxing.services.business.dto.request.modify.*;
import com.molichuxing.services.business.service.OrderExclusivelBizService;
import com.molichuxing.services.business.service.OrderSubscribeBizService;
import com.molichuxing.services.business.service.OrderTradeBizService;
import com.molichuxing.services.exception.OrderExceptionCodeEnum;
import com.molichuxing.services.infrastructure.dto.response.OrderDto;
import com.molichuxing.services.infrastructure.dto.response.OrderExclusivelDto;
import com.molichuxing.services.infrastructure.dto.response.OrderMileageDto;
import com.molichuxing.services.infrastructure.dto.response.OrderSubscribeDto;
import com.molichuxing.services.infrastructure.service.*;
import com.molichuxing.services.property.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 订单交易biz service
 *
 * @author zoumingyu
 * @date 2019年10月28日
 */
@Service("orderTradeBizService")
public class OrderTradeBizServiceImpl implements OrderTradeBizService {
    private static final Logger logger = LoggerFactory.getLogger(OrderTradeBizServiceImpl.class);

    @Resource
    private OrderService orderService;

    @Resource
    private OrderExclusivelService orderExclusivelService;

    @Resource
    private OrderSubscribeService orderSubscribeService;

    @Resource
    private OrderMileageService orderMileageService;

    @Resource
    private OrderAuditService orderAuditService;

    @Resource
    private OrderDeliveryService orderDeliveryService;

    @Resource
    private OrderStatusFlowService orderStatusFlowService;

    @Resource
    private OrderExclusivelBizService orderExclusivelBizService;

    @Resource
    private OrderSubscribeBizService orderSubscribeBizService;

    @Resource
    private OrderScheduleService orderScheduleService;

    /**
     * 订单取消
     *
     * @param modify
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public Boolean modifyCancel(OrderTradeCancelModifyBizDto modifyBizDto) {
        Boolean result = false;
        OrderDto orderDto = orderService.getOrder(modifyBizDto.getOrderCode());
        if (orderDto == null) {
            logger.error("订单({})不存在", modifyBizDto.getOrderCode());
            throw new BizException("订单异常，取消失败");
        }
        // 判断订单类型
        if (OrderTypeEnum.EXCLUSIVEL.equals(orderDto.getType())) {
            // 专属
            OrderExclusivelDto orderExclusivelDto = orderExclusivelService
                    .getOrderExclusivel(modifyBizDto.getOrderCode());
            if (orderExclusivelDto == null) {
                logger.error("专属订单({})不存在", modifyBizDto.getOrderCode());
                throw new BizException("订单异常，取消失败");
            } else if (!orderExclusivelDto.getUserId().equals(modifyBizDto.getUserId())) {
                logger.error("[modifyCancel]专属订单({})不属于该用户({})", modifyBizDto.getOrderCode(), modifyBizDto.getUserId());
                throw new BizException("订单异常，取消失败");
            } else if (!OrderExclusivelStatusEnum.TRADE_UNPAID.equals(orderExclusivelDto.getOrderStatus())) {
                logger.error("[modifyCancel]专属订单({})状态({}:{})不是待支付", modifyBizDto.getOrderCode(),
                        orderExclusivelDto.getOrderStatus().getValue(), orderExclusivelDto.getOrderStatus().getName());
                throw new BizException(OrderExceptionCodeEnum.STATUS_ERROR.getCode(), "此订单状态已发生变化");
            }
            // 修改订单状态（取消订单）
            OrderModifyBizDto modifyDto = new OrderModifyBizDto();
            BeanUtils.copyProperties(modifyBizDto, modifyDto);
            modifyDto.setOrderStatus(OrderExclusivelStatusEnum.TRADE_CANCELED);
            modifyDto.setPreOrderStatus(OrderExclusivelStatusEnum.TRADE_UNPAID);
            result = orderExclusivelBizService.modifyExclusivelStatus(modifyDto);
        } else if (OrderTypeEnum.SUBSCRIBE.equals(orderDto.getType())) {
            // 订阅
            OrderSubscribeDto orderSubscribeDto = orderSubscribeService.getOrderSubscribe(modifyBizDto.getOrderCode());
            if (orderSubscribeDto == null) {
                logger.error("[modifyCancel]订阅订单({})不存在", modifyBizDto.getOrderCode());
                throw new BizException("订单异常，取消失败");
            } else if (!orderSubscribeDto.getUserId().equals(modifyBizDto.getUserId())) {
                logger.error("[modifyCancel]订阅订单({})不属于该用户({})", modifyBizDto.getOrderCode(), modifyBizDto.getUserId());
                throw new BizException("订单异常，取消失败");
            } else if (!OrderSubscribeStatusEnum.TRADE_UNPAID.equals(orderSubscribeDto.getOrderStatus())) {
                logger.error("[modifyCancel]订阅订单({})状态({}:{})不是待支付", modifyBizDto.getOrderCode(),
                        orderSubscribeDto.getOrderStatus().getValue(), orderSubscribeDto.getOrderStatus().getName());
                throw new BizException("此订单状态已发生变化");
            }
            // 修改订单状态（取消订单）
            OrderModifyBizDto modifyDto = new OrderModifyBizDto();
            BeanUtils.copyProperties(modifyBizDto, modifyDto);
            modifyDto.setOrderStatus(OrderSubscribeStatusEnum.TRADE_CANCELED);
            modifyDto.setPreOrderStatus(OrderSubscribeStatusEnum.TRADE_UNPAID);
            result = orderSubscribeBizService.modifySubscribeStatus(modifyDto);
        } else if (OrderTypeEnum.RELET_MILEAGE.equals(orderDto.getType())) {
            // 加购订单
            OrderMileageDto orderMileageDto = orderMileageService.getOrderMileage(modifyBizDto.getOrderCode());
            if (orderMileageDto == null) {
                logger.error("[modifyCancel]订单({})不存在", modifyBizDto.getOrderCode());
                return result;
            } else if (!orderMileageDto.getUserId().equals(modifyBizDto.getUserId())) {
                logger.error("[modifyCancel]加购订单({})不属于该用户({})", modifyBizDto.getOrderCode(), modifyBizDto.getUserId());
                throw new BizException("订单异常，取消失败");
            } else if (!OrderMileagePayStatusEnum.WAIT.equals(orderMileageDto.getStatus())) {
                logger.error("[modifyCancel]加购订单({})状态({}:{})不是待支付", modifyBizDto.getOrderCode(),
                        orderMileageDto.getStatus().getValue(), orderMileageDto.getStatus().getName());
                throw new BizException("此订单状态已发生变化");
            }
            // 修改订单状态（取消订单）
            result = orderMileageService.cancel(modifyBizDto.getOrderCode());
        }
        return result;
    }

    /**
     * 订单审核
     *
     * @param modifyBizDto
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public Boolean modifyAudit(OrderTradeAuditModifyBizDto modifyBizDto) {
        Boolean result = false;
        OrderDto orderDto = orderService.getOrder(modifyBizDto.getOrderCode());
        if (orderDto == null) {
            logger.error("[modifyAudit]订单({})不存在", modifyBizDto.getOrderCode());
            throw new BizException("审核失败，订单不存在");
        }
        // 判断订单类型
        if (OrderTypeEnum.EXCLUSIVEL.equals(orderDto.getType())) {
            // 专属
            OrderExclusivelDto orderExclusivelDto = this.getOrderExclusivelDto(modifyBizDto.getOrderCode(),
                    OrderExclusivelStatusEnum.TRADE_UNAUDIT);
            if (OrderPaymentMethodEnum.FULL.equals(orderExclusivelDto.getPaymentMethod())) {
                logger.error("[modifyAudit]专属订单({})付款方式({})无需审核", modifyBizDto.getOrderCode(),
                        orderExclusivelDto.getPaymentMethod().getName());
                throw new BizException("审核失败，全款订单无需审核");
            }
            // 修改订单状态（审核订单）
            OrderModifyBizDto modifyDto = new OrderModifyBizDto();
            modifyDto.setOrderCode(orderDto.getOrderCode());
            modifyDto.setModifiedType(OrderStatusFlowModifiedTypeEnum.B_USER);
            modifyDto.setOrderStatus(OrderAuditResultEnum.PASS.equals(modifyBizDto.getResult())
                    ? OrderExclusivelStatusEnum.TRADE_UNDELIVERY : OrderExclusivelStatusEnum.TRADE_REJECTED);
            modifyDto.setPreOrderStatus(OrderExclusivelStatusEnum.TRADE_UNAUDIT);
            result = orderExclusivelBizService.modifyExclusivelStatus(modifyDto);
            if (!OrderAuditResultEnum.PASS.equals(modifyBizDto.getResult())) {
                // 审核不通过，需要将排期修改为已取消
                orderScheduleService.modifyCancel(orderDto.getOrderCode());
            }
        } else if (OrderTypeEnum.SUBSCRIBE.equals(orderDto.getType())) {
            // 订阅
            this.getOrderSubscribeDto(modifyBizDto.getOrderCode(), OrderSubscribeStatusEnum.TRADE_UNAUDIT);
            // 修改订单状态（审核订单）
            OrderModifyBizDto modifyDto = new OrderModifyBizDto();
            modifyDto.setOrderCode(orderDto.getOrderCode());
            modifyDto.setModifiedType(OrderStatusFlowModifiedTypeEnum.B_USER);
            modifyDto.setOrderStatus(OrderAuditResultEnum.PASS.equals(modifyBizDto.getResult())
                    ? OrderSubscribeStatusEnum.TRADE_UNDELIVERY : OrderSubscribeStatusEnum.TRADE_REJECTED);
            modifyDto.setPreOrderStatus(OrderSubscribeStatusEnum.TRADE_UNAUDIT);
            result = orderSubscribeBizService.modifySubscribeStatus(modifyDto);
        }
        if (result) {
            // 新增审核信息
            orderAuditService.create(Convert.toOrderAuditCreateDto(modifyBizDto, OrderAuditTypeEnum.BUSINESS));
        }
        return result;
    }

    /**
     * 订单退款
     *
     * @param modifyDto
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public Boolean modifyRefund(OrderTradeRefundModifyBizDto modifyBizDto) {
        Boolean result = false;
        OrderDto orderDto = orderService.getOrder(modifyBizDto.getOrderCode());
        if (orderDto == null) {
            logger.error("[modifyRefund]订单({})不存在", modifyBizDto.getOrderCode());
            throw new BizException("退款失败，订单不存在");
        }
        // 判断订单类型
        if (OrderTypeEnum.EXCLUSIVEL.equals(orderDto.getType())) {
            // 修改订单状态（订单退款）
            OrderModifyBizDto modifyDto = new OrderModifyBizDto();
            BeanUtils.copyProperties(modifyBizDto, modifyDto);
            if (OrderTradeRefundTypeEnum.ISSUE.equals(modifyBizDto.getType())) {
                // 发起退款
                modifyDto.setOrderStatus(OrderExclusivelStatusEnum.TRADE_REFUND);
                modifyDto.setPreOrderStatus(OrderExclusivelStatusEnum.TRADE_REJECTED);
            } else if (OrderTradeRefundTypeEnum.FINISH.equals(modifyBizDto.getType())) {
                // 退款完成
                modifyDto.setOrderStatus(OrderExclusivelStatusEnum.TRADE_FINISH);
                modifyDto.setPreOrderStatus(OrderExclusivelStatusEnum.TRADE_REFUND);
            }
            result = orderExclusivelBizService.modifyExclusivelStatus(modifyDto);
        } else if (OrderTypeEnum.SUBSCRIBE.equals(orderDto.getType())) {
            // 修改订单状态（订单退款）
            OrderModifyBizDto modifyDto = new OrderModifyBizDto();
            BeanUtils.copyProperties(modifyBizDto, modifyDto);
            if (OrderTradeRefundTypeEnum.ISSUE.equals(modifyBizDto.getType())) {
                // 发起退款
                modifyDto.setOrderStatus(OrderSubscribeStatusEnum.TRADE_REFUND);
                modifyDto.setPreOrderStatus(OrderSubscribeStatusEnum.TRADE_REJECTED);
            } else if (OrderTradeRefundTypeEnum.FINISH.equals(modifyBizDto.getType())) {
                // 退款完成
                modifyDto.setOrderStatus(OrderSubscribeStatusEnum.TRADE_FINISH);
                modifyDto.setPreOrderStatus(OrderSubscribeStatusEnum.TRADE_REFUND);
            }
            result = orderSubscribeBizService.modifySubscribeStatus(modifyDto);
        }

        return result;
    }

    /**
     * 订单提车
     *
     * @param modifyDto
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public Boolean modifyDelivery(OrderTradeDeliveryModifyBizDto modifyBizDto) {
        Boolean result = false;
        OrderDto orderDto = orderService.getOrder(modifyBizDto.getOrderCode());
        if (orderDto == null) {
            logger.error("[modifyDelivery]订单({})不存在", modifyBizDto.getOrderCode());
            throw new BizException("提车失败，订单不存在");
        }
        Integer status = null;
        // 判断订单类型
        if (OrderTypeEnum.EXCLUSIVEL.equals(orderDto.getType())) {
            // 修改订单信息（提车）
            status = OrderExclusivelStatusEnum.TRADE_USE.getValue();
            result = orderExclusivelService.modifyDelivery(Convert.toOrderDeliveryModifyDto(modifyBizDto));
        } else if (OrderTypeEnum.SUBSCRIBE.equals(orderDto.getType())) {
            // 修改订单信息（提车）
            status = OrderSubscribeStatusEnum.TRADE_USE.getValue();
            result = orderSubscribeService.modifyDelivery(Convert.toOrderDeliveryModifyDto(modifyBizDto));
        }
        if (result) {
            // 新增流转信息
            orderStatusFlowService.createOrderStatusFlow(Convert.toOrderStatusFlowCreateDto(modifyBizDto, status));
            // 新增提车信息
            orderDeliveryService.create(Convert.toOrderDeliveryCreateDto(modifyBizDto));
        }

        return result;
    }

    private OrderExclusivelDto getOrderExclusivelDto(Long orderCode, OrderExclusivelStatusEnum status) {
        // 专属
        OrderExclusivelDto orderExclusivelDto = orderExclusivelService.getOrderExclusivel(orderCode);
        if (orderExclusivelDto == null) {
            logger.error("[getOrderExclusivelDto]专属订单({})不存在", orderCode);
            throw new BizException("操作失败，订单不存在");
        } else if (!status.equals(orderExclusivelDto.getOrderStatus())) {
            logger.error("[getOrderExclusivelDto]专属订单({})状态({}:{})不是" + status.getName(), orderCode,
                    orderExclusivelDto.getOrderStatus().getValue(), orderExclusivelDto.getOrderStatus().getName());
            throw new BizException("操作失败，此订单不是" + status.getName() + "状态");
        }
        return orderExclusivelDto;
    }

    private OrderSubscribeDto getOrderSubscribeDto(Long orderCode, OrderSubscribeStatusEnum status) {
        // 订阅
        OrderSubscribeDto orderSubscribeDto = orderSubscribeService.getOrderSubscribe(orderCode);
        if (orderSubscribeDto == null) {
            logger.error("[getOrderSubscribeDto]订阅订单({})不存在", orderCode);
            throw new BizException("操作失败，订单不存在");
        } else if (!status.equals(orderSubscribeDto.getOrderStatus())) {
            logger.error("[getOrderSubscribeDto]订阅订单({})状态({}:{})不是" + status.getName(), orderCode,
                    orderSubscribeDto.getOrderStatus().getValue(), orderSubscribeDto.getOrderStatus().getName());
            throw new BizException("操作失败，此订单不是" + status.getName() + "状态");
        }

        return orderSubscribeDto;
    }

    /**
     * 征信审核
     *
     * @param modifyBizDto
     * @return
     */
    @Override
    public Boolean modifyCreditAudit(OrderTradeAuditModifyBizDto modifyBizDto) {
        Boolean result = false;
        // 修改订单状态
        OrderModifyBizDto modifyDto = new OrderModifyBizDto();
        modifyDto.setOrderCode(modifyBizDto.getOrderCode());
        modifyDto.setModifiedType(OrderStatusFlowModifiedTypeEnum.C_USER);
        modifyDto.setOrderStatus(OrderAuditResultEnum.PASS.equals(modifyBizDto.getResult())
                ? OrderExclusivelStatusEnum.TRADE_UNPAID : OrderExclusivelStatusEnum.TRADE_FINISH);
        modifyDto.setPreOrderStatus(OrderExclusivelStatusEnum.TRADE_CREDIT_UNAUDIT);
        result = orderExclusivelBizService.modifyExclusivelStatus(modifyDto);
        if (result) {
            // 新增审核信息
            orderAuditService.create(Convert.toOrderAuditCreateDto(modifyBizDto, OrderAuditTypeEnum.CREDIT));
        }

        return result;
    }
}
